package com.cencat.common.context;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 用户上下文管理器
 * 基于ThreadLocal实现用户信息的线程级存储和管理
 * 
 * @author cencat
 * @since 2024-01-01
 */

public class UserContext {

    private static final Logger log = LoggerFactory.getLogger(UserContext.class);

    /** 用户ID键名 */
    private static final String USER_ID_KEY = "userId";
    
    /** 用户名键名 */
    private static final String USERNAME_KEY = "username";
    
    /** 用户昵称键名 */
    private static final String NICKNAME_KEY = "nickname";
    
    /** 用户角色键名 */
    private static final String ROLES_KEY = "roles";
    
    /** 用户权限键名 */
    private static final String PERMISSIONS_KEY = "permissions";
    
    /** 部门ID键名 */
    private static final String DEPT_ID_KEY = "deptId";
    
    /** 部门名称键名 */
    private static final String DEPT_NAME_KEY = "deptName";
    
    /** 是否超级管理员键名 */
    private static final String IS_SUPER_ADMIN_KEY = "isSuperAdmin";
    
    /** 登录时间键名 */
    private static final String LOGIN_TIME_KEY = "loginTime";
    
    /** 登录IP键名 */
    private static final String LOGIN_IP_KEY = "loginIp";
    
    /** 用户代理键名 */
    private static final String USER_AGENT_KEY = "userAgent";
    
    /** 会话ID键名 */
    private static final String SESSION_ID_KEY = "sessionId";
    
    /** JWT Token键名 */
    private static final String JWT_TOKEN_KEY = "jwtToken";
    
    /** 租户ID键名 */
    private static final String TENANT_ID_KEY = "tenantId";

    /** 用户上下文ThreadLocal */
    private static final ThreadLocal<Map<String, Object>> USER_CONTEXT = new ThreadLocal<>();

    /**
     * 设置用户上下文
     * 
     * @param userInfo 用户信息映射
     */
    public static void setUserContext(Map<String, Object> userInfo) {
        if (userInfo == null) {
            log.warn("设置用户上下文时传入的用户信息为空");
            return;
        }
        
        USER_CONTEXT.set(new HashMap<>(userInfo));
        log.debug("设置用户上下文成功: userId={}, username={}", 
            userInfo.get(USER_ID_KEY), userInfo.get(USERNAME_KEY));
    }

    /**
     * 获取用户上下文
     * 
     * @return 用户信息映射
     */
    public static Map<String, Object> getUserContext() {
        Map<String, Object> context = USER_CONTEXT.get();
        return context != null ? new HashMap<>(context) : new HashMap<>();
    }

    /**
     * 清除用户上下文
     */
    public static void clearUserContext() {
        Map<String, Object> context = USER_CONTEXT.get();
        if (context != null) {
            log.debug("清除用户上下文: userId={}, username={}", 
                context.get(USER_ID_KEY), context.get(USERNAME_KEY));
        }
        USER_CONTEXT.remove();
    }

    /**
     * 清除用户上下文（别名方法）
     */
    public static void clear() {
        clearUserContext();
    }

    /**
     * 获取当前用户ID
     * 
     * @return 用户ID
     */
    public static Long getCurrentUserId() {
        Object userId = getContextValue(USER_ID_KEY);
        if (userId == null) {
            return null;
        }
        
        if (userId instanceof Long) {
            return (Long) userId;
        } else if (userId instanceof String) {
            try {
                return Long.parseLong((String) userId);
            } catch (NumberFormatException e) {
                log.warn("用户ID格式转换失败: {}", userId);
                return null;
            }
        } else if (userId instanceof Number) {
            return ((Number) userId).longValue();
        }
        
        log.warn("用户ID类型不支持: {}", userId.getClass().getName());
        return null;
    }

    /**
     * 设置当前用户ID
     * 
     * @param userId 用户ID
     */
    public static void setCurrentUserId(Long userId) {
        setContextValue(USER_ID_KEY, userId);
        log.debug("设置当前用户ID: {}", userId);
    }

    /**
     * 获取当前用户名
     * 
     * @return 用户名
     */
    public static String getCurrentUsername() {
        return (String) getContextValue(USERNAME_KEY);
    }

    /**
     * 设置当前用户名
     * 
     * @param username 用户名
     */
    public static void setCurrentUsername(String username) {
        setContextValue(USERNAME_KEY, username);
        log.debug("设置当前用户名: {}", username);
    }

    /**
     * 获取当前用户昵称
     * 
     * @return 用户昵称
     */
    public static String getCurrentNickname() {
        return (String) getContextValue(NICKNAME_KEY);
    }

    /**
     * 设置当前用户昵称
     * 
     * @param nickname 用户昵称
     */
    public static void setCurrentNickname(String nickname) {
        setContextValue(NICKNAME_KEY, nickname);
    }

    /**
     * 获取当前用户角色
     * 
     * @return 用户角色集合
     */
    @SuppressWarnings("unchecked")
    public static Set<String> getCurrentRoles() {
        return (Set<String>) getContextValue(ROLES_KEY);
    }

    /**
     * 设置当前用户角色
     * 
     * @param roles 用户角色集合
     */
    public static void setCurrentRoles(Set<String> roles) {
        setContextValue(ROLES_KEY, roles);
    }

    /**
     * 设置当前用户角色（别名方法）
     * 
     * @param roles 用户角色集合
     */
    public static void setCurrentUserRoles(Set<String> roles) {
        setCurrentRoles(roles);
    }

    /**
     * 获取当前用户权限
     * 
     * @return 用户权限集合
     */
    @SuppressWarnings("unchecked")
    public static Set<String> getCurrentPermissions() {
        return (Set<String>) getContextValue(PERMISSIONS_KEY);
    }

    /**
     * 设置当前用户权限
     * 
     * @param permissions 用户权限集合
     */
    public static void setCurrentPermissions(Set<String> permissions) {
        setContextValue(PERMISSIONS_KEY, permissions);
    }

    /**
     * 获取当前部门ID
     * 
     * @return 部门ID
     */
    public static Long getCurrentDeptId() {
        Object deptId = getContextValue(DEPT_ID_KEY);
        if (deptId == null) {
            return null;
        }
        
        if (deptId instanceof Long) {
            return (Long) deptId;
        } else if (deptId instanceof String) {
            try {
                return Long.parseLong((String) deptId);
            } catch (NumberFormatException e) {
                log.warn("部门ID格式转换失败: {}", deptId);
                return null;
            }
        } else if (deptId instanceof Number) {
            return ((Number) deptId).longValue();
        }
        
        return null;
    }

    /**
     * 设置当前部门ID
     * 
     * @param deptId 部门ID
     */
    public static void setCurrentDeptId(Long deptId) {
        setContextValue(DEPT_ID_KEY, deptId);
    }

    /**
     * 获取当前部门名称
     * 
     * @return 部门名称
     */
    public static String getCurrentDeptName() {
        return (String) getContextValue(DEPT_NAME_KEY);
    }

    /**
     * 设置当前部门名称
     * 
     * @param deptName 部门名称
     */
    public static void setCurrentDeptName(String deptName) {
        setContextValue(DEPT_NAME_KEY, deptName);
    }

    /**
     * 判断当前用户是否为超级管理员
     * 
     * @return true-是超级管理员，false-不是
     */
    public static boolean isSuperAdmin() {
        Object isSuperAdmin = getContextValue(IS_SUPER_ADMIN_KEY);
        if (isSuperAdmin == null) {
            return false;
        }
        
        if (isSuperAdmin instanceof Boolean) {
            return (Boolean) isSuperAdmin;
        } else if (isSuperAdmin instanceof String) {
            return Boolean.parseBoolean((String) isSuperAdmin);
        }
        
        return false;
    }

    /**
     * 设置当前用户是否为超级管理员
     * 
     * @param isSuperAdmin 是否为超级管理员
     */
    public static void setSuperAdmin(boolean isSuperAdmin) {
        setContextValue(IS_SUPER_ADMIN_KEY, isSuperAdmin);
    }

    /**
     * 获取登录时间
     * 
     * @return 登录时间
     */
    public static java.time.LocalDateTime getLoginTime() {
        return (java.time.LocalDateTime) getContextValue(LOGIN_TIME_KEY);
    }

    /**
     * 设置登录时间
     * 
     * @param loginTime 登录时间
     */
    public static void setLoginTime(java.time.LocalDateTime loginTime) {
        setContextValue(LOGIN_TIME_KEY, loginTime);
    }

    /**
     * 获取登录IP
     * 
     * @return 登录IP
     */
    public static String getLoginIp() {
        return (String) getContextValue(LOGIN_IP_KEY);
    }

    /**
     * 设置登录IP
     * 
     * @param loginIp 登录IP
     */
    public static void setLoginIp(String loginIp) {
        setContextValue(LOGIN_IP_KEY, loginIp);
    }

    /**
     * 获取用户代理
     * 
     * @return 用户代理
     */
    public static String getUserAgent() {
        return (String) getContextValue(USER_AGENT_KEY);
    }

    /**
     * 设置用户代理
     * 
     * @param userAgent 用户代理
     */
    public static void setUserAgent(String userAgent) {
        setContextValue(USER_AGENT_KEY, userAgent);
    }

    /**
     * 获取会话ID
     * 
     * @return 会话ID
     */
    public static String getSessionId() {
        return (String) getContextValue(SESSION_ID_KEY);
    }

    /**
     * 设置会话ID
     * 
     * @param sessionId 会话ID
     */
    public static void setSessionId(String sessionId) {
        setContextValue(SESSION_ID_KEY, sessionId);
    }

    /**
     * 获取JWT Token
     * 
     * @return JWT Token
     */
    public static String getJwtToken() {
        return (String) getContextValue(JWT_TOKEN_KEY);
    }

    /**
     * 设置JWT Token
     * 
     * @param jwtToken JWT Token
     */
    public static void setJwtToken(String jwtToken) {
        setContextValue(JWT_TOKEN_KEY, jwtToken);
    }

    /**
     * 获取当前租户ID
     * 
     * @return 租户ID
     */
    public static Long getCurrentTenantId() {
        Object tenantId = getContextValue(TENANT_ID_KEY);
        if (tenantId == null) {
            return null;
        }
        
        if (tenantId instanceof Long) {
            return (Long) tenantId;
        } else if (tenantId instanceof String) {
            try {
                return Long.parseLong((String) tenantId);
            } catch (NumberFormatException e) {
                log.warn("租户ID格式转换失败: {}", tenantId);
                return null;
            }
        } else if (tenantId instanceof Number) {
            return ((Number) tenantId).longValue();
        }
        
        return null;
    }

    /**
     * 设置当前租户ID
     * 
     * @param tenantId 租户ID
     */
    public static void setCurrentTenantId(Long tenantId) {
        setContextValue(TENANT_ID_KEY, tenantId);
    }

    /**
     * 检查用户是否已登录
     * 
     * @return true-已登录，false-未登录
     */
    public static boolean isLoggedIn() {
        return getCurrentUserId() != null;
    }

    /**
     * 检查用户是否有指定角色
     * 
     * @param role 角色名称
     * @return true-有该角色，false-没有该角色
     */
    public static boolean hasRole(String role) {
        if (role == null || role.trim().isEmpty()) {
            return false;
        }
        
        Set<String> roles = getCurrentRoles();
        return roles != null && roles.contains(role);
    }

    /**
     * 检查用户是否有指定权限
     * 
     * @param permission 权限名称
     * @return true-有该权限，false-没有该权限
     */
    public static boolean hasPermission(String permission) {
        if (permission == null || permission.trim().isEmpty()) {
            return false;
        }
        
        // 超级管理员拥有所有权限
        if (isSuperAdmin()) {
            return true;
        }
        
        Set<String> permissions = getCurrentPermissions();
        return permissions != null && permissions.contains(permission);
    }

    /**
     * 检查用户是否有任意一个指定权限
     * 
     * @param permissions 权限名称数组
     * @return true-有任意一个权限，false-没有任何权限
     */
    public static boolean hasAnyPermission(String... permissions) {
        if (permissions == null || permissions.length == 0) {
            return false;
        }
        
        for (String permission : permissions) {
            if (hasPermission(permission)) {
                return true;
            }
        }
        
        return false;
    }

    /**
     * 检查用户是否拥有所有指定权限
     * 
     * @param permissions 权限名称数组
     * @return true-拥有所有权限，false-缺少某些权限
     */
    public static boolean hasAllPermissions(String... permissions) {
        if (permissions == null || permissions.length == 0) {
            return true;
        }
        
        for (String permission : permissions) {
            if (!hasPermission(permission)) {
                return false;
            }
        }
        
        return true;
    }

    /**
     * 获取上下文值
     * 
     * @param key 键名
     * @return 值
     */
    private static Object getContextValue(String key) {
        Map<String, Object> context = USER_CONTEXT.get();
        return context != null ? context.get(key) : null;
    }

    /**
     * 设置上下文值
     * 
     * @param key 键名
     * @param value 值
     */
    private static void setContextValue(String key, Object value) {
        Map<String, Object> context = USER_CONTEXT.get();
        if (context == null) {
            context = new HashMap<>();
            USER_CONTEXT.set(context);
        }
        context.put(key, value);
    }

    /**
     * 移除上下文值
     * 
     * @param key 键名
     */
    public static void removeContextValue(String key) {
        Map<String, Object> context = USER_CONTEXT.get();
        if (context != null) {
            context.remove(key);
        }
    }

    /**
     * 检查上下文是否包含指定键
     * 
     * @param key 键名
     * @return true-包含，false-不包含
     */
    public static boolean containsKey(String key) {
        Map<String, Object> context = USER_CONTEXT.get();
        return context != null && context.containsKey(key);
    }

    /**
     * 获取上下文大小
     * 
     * @return 上下文大小
     */
    public static int getContextSize() {
        Map<String, Object> context = USER_CONTEXT.get();
        return context != null ? context.size() : 0;
    }

    /**
     * 检查上下文是否为空
     * 
     * @return true-为空，false-不为空
     */
    public static boolean isContextEmpty() {
        return getContextSize() == 0;
    }

    /**
     * 用户信息构建器
     */
    public static class UserInfoBuilder {
        private final Map<String, Object> userInfo = new HashMap<>();

        public UserInfoBuilder userId(Long userId) {
            userInfo.put(USER_ID_KEY, userId);
            return this;
        }

        public UserInfoBuilder username(String username) {
            userInfo.put(USERNAME_KEY, username);
            return this;
        }

        public UserInfoBuilder nickname(String nickname) {
            userInfo.put(NICKNAME_KEY, nickname);
            return this;
        }

        public UserInfoBuilder roles(Set<String> roles) {
            userInfo.put(ROLES_KEY, roles);
            return this;
        }

        public UserInfoBuilder permissions(Set<String> permissions) {
            userInfo.put(PERMISSIONS_KEY, permissions);
            return this;
        }

        public UserInfoBuilder deptId(Long deptId) {
            userInfo.put(DEPT_ID_KEY, deptId);
            return this;
        }

        public UserInfoBuilder deptName(String deptName) {
            userInfo.put(DEPT_NAME_KEY, deptName);
            return this;
        }

        public UserInfoBuilder superAdmin(boolean isSuperAdmin) {
            userInfo.put(IS_SUPER_ADMIN_KEY, isSuperAdmin);
            return this;
        }

        public UserInfoBuilder loginTime(java.time.LocalDateTime loginTime) {
            userInfo.put(LOGIN_TIME_KEY, loginTime);
            return this;
        }

        public UserInfoBuilder loginIp(String loginIp) {
            userInfo.put(LOGIN_IP_KEY, loginIp);
            return this;
        }

        public UserInfoBuilder userAgent(String userAgent) {
            userInfo.put(USER_AGENT_KEY, userAgent);
            return this;
        }

        public UserInfoBuilder sessionId(String sessionId) {
            userInfo.put(SESSION_ID_KEY, sessionId);
            return this;
        }

        public UserInfoBuilder jwtToken(String jwtToken) {
            userInfo.put(JWT_TOKEN_KEY, jwtToken);
            return this;
        }

        public Map<String, Object> build() {
            return new HashMap<>(userInfo);
        }

        public void buildAndSet() {
            UserContext.setUserContext(build());
        }
    }

    /**
     * 创建用户信息构建器
     * 
     * @return 用户信息构建器
     */
    public static UserInfoBuilder builder() {
        return new UserInfoBuilder();
    }
}